#include "StdAfx.h"
#include "ActiveXCtrl.h"
#include "ActiveXWnd.h"
#include "ActiveXEnum.h"
#include "ActiveXFrameWnd.h"

CActiveXCtrl::CActiveXCtrl(void): 
m_dwRef(1), 
m_pOwner(NULL), 
m_pWindow(NULL),
m_pUnkSite(NULL), 
m_pViewObject(NULL),
m_pInPlaceObject(NULL),
m_bLocked(false), 
m_bFocused(false),
m_bCaptured(false),
m_bWindowless(true),
m_bUIActivated(false),
m_bInPlaceActive(false)
{
}

CActiveXCtrl::~CActiveXCtrl(void)
{
	if( m_pWindow != NULL ) ::DestroyWindow(*m_pWindow);
	if( m_pUnkSite != NULL ) m_pUnkSite->Release();
	if( m_pViewObject != NULL ) m_pViewObject->Release();
	if( m_pInPlaceObject != NULL ) m_pInPlaceObject->Release();
}


STDMETHODIMP CActiveXCtrl::QueryInterface(REFIID riid, LPVOID *ppvObject)
{
	*ppvObject = NULL;
	if( riid == IID_IUnknown )                       *ppvObject = static_cast<IOleWindow*>(this);
	else if( riid == IID_IOleClientSite )            *ppvObject = static_cast<IOleClientSite*>(this);
	else if( riid == IID_IOleInPlaceSiteWindowless ) *ppvObject = static_cast<IOleInPlaceSiteWindowless*>(this);
	else if( riid == IID_IOleInPlaceSiteEx )         *ppvObject = static_cast<IOleInPlaceSiteEx*>(this);
	else if( riid == IID_IOleInPlaceSite )           *ppvObject = static_cast<IOleInPlaceSite*>(this);
	else if( riid == IID_IOleWindow )                *ppvObject = static_cast<IOleWindow*>(this);
	else if( riid == IID_IOleControlSite )           *ppvObject = static_cast<IOleControlSite*>(this);
	else if( riid == IID_IOleContainer )             *ppvObject = static_cast<IOleContainer*>(this);
	else if( riid == IID_IObjectWithSite )           *ppvObject = static_cast<IObjectWithSite*>(this);
	if( *ppvObject != NULL ) AddRef();
	return *ppvObject == NULL ? E_NOINTERFACE : S_OK;
}

STDMETHODIMP_(ULONG) CActiveXCtrl::AddRef()
{
	return ++m_dwRef;
}

STDMETHODIMP_(ULONG) CActiveXCtrl::Release()
{
	LONG lRef = --m_dwRef;
	if( lRef == 0 ) delete this;
	return lRef;
}

STDMETHODIMP CActiveXCtrl::SetSite(IUnknown *pUnkSite)
{
	OutputDebugString(L"AX: CActiveXCtrl::SetSite");
	if( m_pUnkSite != NULL ) {
		m_pUnkSite->Release();
		m_pUnkSite = NULL;
	}
	if( pUnkSite != NULL ) {
		m_pUnkSite = pUnkSite;
		m_pUnkSite->AddRef();
	}
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::GetSite(REFIID riid, LPVOID* ppvSite)
{
	OutputDebugString(L"AX: CActiveXCtrl::GetSite");
	if( ppvSite == NULL ) return E_POINTER;
	*ppvSite = NULL;
	if( m_pUnkSite == NULL ) return E_FAIL;
	return m_pUnkSite->QueryInterface(riid, ppvSite);
}

STDMETHODIMP CActiveXCtrl::SaveObject(void)
{
	OutputDebugString(L"AX: CActiveXCtrl::SaveObject");
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXCtrl::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk)
{
	OutputDebugString(L"AX: CActiveXCtrl::GetMoniker");
	if( ppmk != NULL ) *ppmk = NULL;
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXCtrl::GetContainer(IOleContainer** ppContainer)
{
	OutputDebugString(L"AX: CActiveXCtrl::GetContainer");
	if( ppContainer == NULL ) return E_POINTER;
	*ppContainer = NULL;
	HRESULT Hr = E_NOTIMPL;
	if( m_pUnkSite != NULL ) Hr = m_pUnkSite->QueryInterface(IID_IOleContainer, (LPVOID*) ppContainer);
	if( FAILED(Hr) ) Hr = QueryInterface(IID_IOleContainer, (LPVOID*) ppContainer);
	return Hr;
}

STDMETHODIMP CActiveXCtrl::ShowObject(void)
{
	OutputDebugString(L"AX: CActiveXCtrl::ShowObject");
	if( m_pOwner == NULL ) return E_UNEXPECTED;
	HDC hDC = ::GetDC(m_pOwner->m_hwndHost);
	if( hDC == NULL ) return E_FAIL;
	if( m_pViewObject != NULL ) m_pViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, hDC, (RECTL*) &m_pOwner->m_rcItem, (RECTL*) &m_pOwner->m_rcItem, NULL, NULL);
	::ReleaseDC(m_pOwner->m_hwndHost, hDC);
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::OnShowWindow(BOOL fShow)
{
	OutputDebugString(L"AX: CActiveXCtrl::OnShowWindow");
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXCtrl::RequestNewObjectLayout(void)
{
	OutputDebugString(L"AX: CActiveXCtrl::RequestNewObjectLayout");
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXCtrl::CanWindowlessActivate(void)
{
	OutputDebugString(L"AX: CActiveXCtrl::CanWindowlessActivate");
	return S_OK;  // Yes, we can!!
}

STDMETHODIMP CActiveXCtrl::GetCapture(void)
{
	OutputDebugString(L"AX: CActiveXCtrl::GetCapture");
	if( m_pOwner == NULL ) return E_UNEXPECTED;
	return m_bCaptured ? S_OK : S_FALSE;
}

STDMETHODIMP CActiveXCtrl::SetCapture(BOOL fCapture)
{
	OutputDebugString(L"AX: CActiveXCtrl::SetCapture");
	if( m_pOwner == NULL ) return E_UNEXPECTED;
	m_bCaptured = (fCapture == TRUE);
	if( fCapture ) ::SetCapture(m_pOwner->m_hwndHost); else ::ReleaseCapture();
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::GetFocus(void)
{
	OutputDebugString(L"AX: CActiveXCtrl::GetFocus");
	if( m_pOwner == NULL ) return E_UNEXPECTED;
	return m_bFocused ? S_OK : S_FALSE;
}

STDMETHODIMP CActiveXCtrl::SetFocus(BOOL fFocus)
{
	OutputDebugString(L"AX: CActiveXCtrl::SetFocus");
	if( m_pOwner == NULL ) return E_UNEXPECTED;
	if( fFocus ) m_pOwner->SetFocus();
	m_bFocused = (fFocus == TRUE);
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::GetDC(LPCRECT pRect, DWORD grfFlags, HDC* phDC)
{
	OutputDebugString(L"AX: CActiveXCtrl::GetDC");
	if( phDC == NULL ) return E_POINTER;
	if( m_pOwner == NULL ) return E_UNEXPECTED;
	*phDC = ::GetDC(m_pOwner->m_hwndHost);
	if( (grfFlags & OLEDC_PAINTBKGND) != 0 ) {
		CStdRect rcItem = m_pOwner->GetPos();
		if( !m_bWindowless ) rcItem.ResetOffset();
		::FillRect(*phDC, &rcItem, (HBRUSH) (COLOR_WINDOW + 1));
	}
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::ReleaseDC(HDC hDC)
{
	OutputDebugString(L"AX: CActiveXCtrl::ReleaseDC");
	if( m_pOwner == NULL ) return E_UNEXPECTED;
	::ReleaseDC(m_pOwner->m_hwndHost, hDC);
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::InvalidateRect(LPCRECT pRect, BOOL fErase)
{
	OutputDebugString(L"AX: CActiveXCtrl::InvalidateRect");
	if( m_pOwner == NULL ) return E_UNEXPECTED;
	if( m_pOwner->m_hwndHost == NULL ) return E_FAIL;
	return ::InvalidateRect(m_pOwner->m_hwndHost, pRect, fErase) ? S_OK : E_FAIL;
}

STDMETHODIMP CActiveXCtrl::InvalidateRgn(HRGN hRGN, BOOL fErase)
{
	OutputDebugString(L"AX: CActiveXCtrl::InvalidateRgn");
	if( m_pOwner == NULL ) return E_UNEXPECTED;
	return ::InvalidateRgn(m_pOwner->m_hwndHost, hRGN, fErase) ? S_OK : E_FAIL;
}

STDMETHODIMP CActiveXCtrl::ScrollRect(INT dx, INT dy, LPCRECT pRectScroll, LPCRECT pRectClip)
{
	OutputDebugString(L"AX: CActiveXCtrl::ScrollRect");
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::AdjustRect(LPRECT prc)
{
	OutputDebugString(L"AX: CActiveXCtrl::AdjustRect");
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::OnDefWindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* plResult)
{
	OutputDebugString(L"AX: CActiveXCtrl::OnDefWindowMessage");
	if( m_pOwner == NULL ) return E_UNEXPECTED;
	*plResult = ::DefWindowProc(m_pOwner->m_hwndHost, msg, wParam, lParam);
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::OnInPlaceActivateEx(BOOL* pfNoRedraw, DWORD dwFlags)        
{
	OutputDebugString(L"AX: CActiveXCtrl::OnInPlaceActivateEx");
	ASSERT(m_pInPlaceObject==NULL);
	if( m_pOwner == NULL ) return E_UNEXPECTED;
	if( m_pOwner->m_pUnk == NULL ) return E_UNEXPECTED;
	::OleLockRunning(m_pOwner->m_pUnk, TRUE, FALSE);
	HWND hWndFrame = m_pOwner->GetManager()->GetPaintWindow();
	HRESULT Hr = E_FAIL;
	if( (dwFlags & ACTIVATE_WINDOWLESS) != 0 ) {
		m_bWindowless = true;
		Hr = m_pOwner->m_pUnk->QueryInterface(IID_IOleInPlaceObjectWindowless, (LPVOID*) &m_pInPlaceObject);
		m_pOwner->m_hwndHost = hWndFrame;
		m_pOwner->GetManager()->AddMessageFilter(m_pOwner);
	}
	if( FAILED(Hr) ) {
		m_bWindowless = false;
		Hr = CreateActiveXWnd();
		if( FAILED(Hr) ) return Hr;
		Hr = m_pOwner->m_pUnk->QueryInterface(IID_IOleInPlaceObject, (LPVOID*) &m_pInPlaceObject);
	}
	if( m_pInPlaceObject != NULL ) {
		CStdRect rcItem = m_pOwner->m_rcItem;
		if( !m_bWindowless ) rcItem.ResetOffset();
		m_pInPlaceObject->SetObjectRects(&rcItem, &rcItem);
	}
	m_bInPlaceActive = SUCCEEDED(Hr);
	return Hr;
}

STDMETHODIMP CActiveXCtrl::OnInPlaceDeactivateEx(BOOL fNoRedraw)       
{
	OutputDebugString(L"AX: CActiveXCtrl::OnInPlaceDeactivateEx");
	m_bInPlaceActive = false;
	if( m_pInPlaceObject != NULL ) {
		m_pInPlaceObject->Release();
		m_pInPlaceObject = NULL;
	}
	if( m_pWindow != NULL ) {
		::DestroyWindow(*m_pWindow);
		m_pWindow = NULL;
	}
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::RequestUIActivate(void)
{
	OutputDebugString(L"AX: CActiveXCtrl::RequestUIActivate");
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::CanInPlaceActivate(void)       
{
	OutputDebugString(L"AX: CActiveXCtrl::CanInPlaceActivate");
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::OnInPlaceActivate(void)
{
	OutputDebugString(L"AX: CActiveXCtrl::OnInPlaceActivate");
	BOOL bDummy = FALSE;
	return OnInPlaceActivateEx(&bDummy, 0);
}

STDMETHODIMP CActiveXCtrl::OnUIActivate(void)
{
	OutputDebugString(L"AX: CActiveXCtrl::OnUIActivate");
	m_bUIActivated = true;
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::GetWindowContext(IOleInPlaceFrame** ppFrame, IOleInPlaceUIWindow** ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
{
	OutputDebugString(L"AX: CActiveXCtrl::GetWindowContext");
	if( ppDoc == NULL ) return E_POINTER;
	if( ppFrame == NULL ) return E_POINTER;
	if( lprcPosRect == NULL ) return E_POINTER;
	if( lprcClipRect == NULL ) return E_POINTER;
	*ppFrame = new CActiveXFrameWnd(m_pOwner);
	*ppDoc = NULL;
	ACCEL ac = { 0 };
	HACCEL hac = ::CreateAcceleratorTable(&ac, 1);
	lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
	lpFrameInfo->fMDIApp = FALSE;
	lpFrameInfo->hwndFrame = m_pOwner->GetManager()->GetPaintWindow();
	lpFrameInfo->haccel = hac;
	lpFrameInfo->cAccelEntries = 1;
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::Scroll(SIZE scrollExtant)
{
	OutputDebugString(L"AX: CActiveXCtrl::Scroll");
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXCtrl::OnUIDeactivate(BOOL fUndoable)
{
	OutputDebugString(L"AX: CActiveXCtrl::OnUIDeactivate");
	m_bUIActivated = false;
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::OnInPlaceDeactivate(void)
{
	OutputDebugString(L"AX: CActiveXCtrl::OnInPlaceDeactivate");
	return OnInPlaceDeactivateEx(TRUE);
}

STDMETHODIMP CActiveXCtrl::DiscardUndoState(void)
{
	OutputDebugString(L"AX: CActiveXCtrl::DiscardUndoState");
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXCtrl::DeactivateAndUndo(void)
{
	OutputDebugString(L"AX: CActiveXCtrl::DeactivateAndUndo");
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXCtrl::OnPosRectChange(LPCRECT lprcPosRect)
{
	OutputDebugString(L"AX: CActiveXCtrl::OnPosRectChange");
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXCtrl::GetWindow(HWND* phwnd)
{
	OutputDebugString(L"AX: CActiveXCtrl::GetWindow");
	if( m_pOwner == NULL ) return E_UNEXPECTED;
	if( m_pOwner->m_hwndHost == NULL ) CreateActiveXWnd();
	if( m_pOwner->m_hwndHost == NULL ) return E_FAIL;
	*phwnd = m_pOwner->m_hwndHost;
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::ContextSensitiveHelp(BOOL fEnterMode)
{
	OutputDebugString(L"AX: CActiveXCtrl::ContextSensitiveHelp");
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::OnControlInfoChanged(void)      
{
	OutputDebugString(L"AX: CActiveXCtrl::OnControlInfoChanged");
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::LockInPlaceActive(BOOL fLock)       
{
	OutputDebugString(L"AX: CActiveXCtrl::LockInPlaceActive");
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::GetExtendedControl(IDispatch** ppDisp)        
{
	OutputDebugString(L"AX: CActiveXCtrl::GetExtendedControl");
	if( ppDisp == NULL ) return E_POINTER;   
	if( m_pOwner == NULL ) return E_UNEXPECTED;
	if( m_pOwner->m_pUnk == NULL ) return E_UNEXPECTED;
	return m_pOwner->m_pUnk->QueryInterface(IID_IDispatch, (LPVOID*) ppDisp);
}

STDMETHODIMP CActiveXCtrl::TransformCoords(POINTL* pPtlHimetric, POINTF* pPtfContainer, DWORD dwFlags)       
{
	OutputDebugString(L"AX: CActiveXCtrl::TransformCoords");
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::TranslateAccelerator(MSG *pMsg, DWORD grfModifiers)
{
	OutputDebugString(L"AX: CActiveXCtrl::TranslateAccelerator");
	return S_FALSE;
}

STDMETHODIMP CActiveXCtrl::OnFocus(BOOL fGotFocus)
{
	OutputDebugString(L"AX: CActiveXCtrl::OnFocus");
	m_bFocused = (fGotFocus == TRUE);
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::ShowPropertyFrame(void)
{
	OutputDebugString(L"AX: CActiveXCtrl::ShowPropertyFrame");
	return E_NOTIMPL;
}

STDMETHODIMP CActiveXCtrl::EnumObjects(DWORD grfFlags, IEnumUnknown** ppenum)
{
	OutputDebugString(L"AX: CActiveXCtrl::EnumObjects");
	if( ppenum == NULL ) return E_POINTER;
	if( m_pOwner == NULL ) return E_UNEXPECTED;
	*ppenum = new CActiveXEnum(m_pOwner->m_pUnk);
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::LockContainer(BOOL fLock)
{
	OutputDebugString(L"AX: CActiveXCtrl::LockContainer");
	m_bLocked = fLock != FALSE;
	return S_OK;
}

STDMETHODIMP CActiveXCtrl::ParseDisplayName(IBindCtx *pbc, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
{
	OutputDebugString(L"AX: CActiveXCtrl::ParseDisplayName");
	return E_NOTIMPL;
}

HRESULT CActiveXCtrl::CreateActiveXWnd()
{
	if( m_pWindow != NULL ) return S_OK;
	m_pWindow = new CActiveXWnd;
	if( m_pWindow == NULL ) return E_OUTOFMEMORY;
	m_pOwner->m_hwndHost = m_pWindow->Init(this, m_pOwner->GetManager()->GetPaintWindow());
	return S_OK;
}